package com.superhelper.superhelper_web.service.deliver;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.superhelper.common.Consts;
import com.superhelper.common.domain.AuserDeliver;
import com.superhelper.common.domain.AuserShop;
import com.superhelper.common.domain.DadaReasons;
import com.superhelper.common.domain.DeliverRecord;
import com.superhelper.common.domain.DeliverRecordStatus;
import com.superhelper.common.domain.OrderCategory;
import com.superhelper.common.domain.TakeOutOrder;
import com.superhelper.common.domain.TakeOutOrderStatus;
import com.superhelper.common.domain.Task;
import com.superhelper.common.exception.ServiceException;
import com.superhelper.common.mapper.DeliverMapper;
import com.superhelper.common.mapper.DeliverRecordMapper;
import com.superhelper.common.mapper.TakeOutOrderMapper;
import com.superhelper.common.utils.JsonHelper;
import com.superhelper.superhelper_web.utils.HttpClientHelper;

@Service
public class DaDaDeliverService implements IDeliverService {
    private static final Logger log = LoggerFactory.getLogger(DaDaDeliverService.class);

    @Autowired
    private TakeOutOrderMapper orderMapper;

    @Autowired
    private DeliverRecordMapper deliverRecordMapper;

    @Autowired
    private com.superhelper.common.mapper.TaskMapper taskMapper;

    @Autowired
    private DeliverMapper deliverMapper;

    @Value("${dada.key}")
    private String appKey;
    @Value("${dada.secret}")
    private String appSecret;

    @Value("${dada.host}")
    private String host;
    @Value("${dada.callback}")
    private String callback;
    private static final String QUERY = "/api/order/queryDeliverFee";

    private static final String ADD = "/api/order/addOrder";

    private static final String ADDTIP = "/api/order/addTip";

    private static final String CANCEL = "/api/order/formalCancel";

    private static final String CANCEL_REASONS = "/api/order/cancel/reasons";

    public TakeOutOrder queryDeliverFee(Long orderId) {
        try {
            TakeOutOrder order = orderMapper.getById(orderId);
            if (!order.getStatus().equalsIgnoreCase(TakeOutOrderStatus.VALID.getValue())) {
                return null;
            }
            AuserShop shop = orderMapper.getShop(order.getShopId(), order.getType());
            // 调用查询接口

            Map<String, Object> resultMap = query(order, shop);
            if ((Integer) resultMap.get("code") == 0) {
                resultMap = (Map) resultMap.get("result");
                order.setDeliverFee((Double) resultMap.get("fee"));
                return order;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            log.error("", e);
        }
        return null;
    }

    public boolean addTask(Long orderId) {
        try {
            TakeOutOrder order = orderMapper.getById(orderId);
            // if (!order.getStatus().equalsIgnoreCase(
            // TakeOutOrderStatus.VALID.getValue())) {
            // return false;
            // }
            AuserShop shop = orderMapper.getShop(order.getShopId(), order.getType());
            return this.addTask(order, shop);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error("", e);
        }
        return false;
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean addTips(Long id, Double tip) throws Exception {
        // TODO Auto-generated method stub
        try {
            DeliverRecord dr = deliverRecordMapper.getById(id);
            TakeOutOrder entity = orderMapper.getById(dr.getOrderId());
            if (!entity.getStatus().equalsIgnoreCase(TakeOutOrderStatus.VALID.getValue())) {
                return false;
            }
            AuserShop shop = orderMapper.getShop(entity.getShopId(), entity.getType());
            // Order order = new Order();
            // BeanUtils.copyProperties(order, entity);

            if (dr.getStatus() == -1 || dr.getStatus() == 1) {// 待接单和异常单
                // order.setTips(dr.getCurrentTip() + tip);
                String uri = host + ADDTIP;
                String body = buildAddTipBody(String.valueOf(dr.getId()), tip);
                String req = buildRequest(body, entity, shop);
                String resp = HttpClientHelper.doPost(uri, req);
                log.info("request:{},response:{}", req, resp);
                if (StringUtils.isNotBlank(resp)) {
                    Map<String, Object> result = JsonHelper.fromJson(resp, Map.class);
                    if (0 == (Integer) result.get("code")) {
                        return true;
                    } else {
                        throw new ServiceException(-1, result.get("msg") + "");
                    }
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error("", e);
            if (e instanceof ServiceException) {
                throw e;
            }
        }
        return false;
    }

    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
    private boolean addTask(TakeOutOrder order, AuserShop shop) throws Exception {
        DeliverRecord dr = orderMapper.getDeliverRecordByOrderId(order.getId());
        if (dr != null && dr.getStatus() != 5 && dr.getStatus() != 4) {
            log.info("has deliver success, orderId:{}", order.getId());
            return true;
        }
        // 添加一条记录到DeliveryRecord
        if (dr == null || dr.getStatus() == 5 || dr.getStatus() == 4) {
            if (dr == null) {
                dr = new DeliverRecord();
            } else {
                dr.setId(null);
                dr.setExtId(dr.getExtId() + 1);
            }
            int orderCategory = OrderCategory.normal.getVal();
            dr.setOrderCategory(orderCategory);
            dr.setStatus(DeliverRecordStatus.unsend.getVal());
            dr.setDeliverFee(0d);
            dr.setDeliverNo(null);
            dr.setCreateAt(new Date());
            dr.setCurrentTip(0d);
            dr.setDeliverAt(new Date());
            dr.setOrderId(order.getId());
            dr.setAuserShopId(shop.getId());
            dr.setDeliverPlf("dada");
            AuserDeliver deliver = deliverMapper.getAuserDeliver(shop.getAuserId());
            if (deliver != null) {
                dr.setPerTip(deliver.getPart_money().doubleValue());
                dr.setMaxTip(deliver.getMax_money().doubleValue());
            } else {
                dr.setPerTip(0d);
                dr.setMaxTip(0d);
            }
            deliverRecordMapper.addDeliverRecord(dr);
        }
        Task task = new Task();
        task.setFlag(0);
        task.setRetryTimes(0);
        task.setType(Consts.Task.deliver_record);
        if (taskMapper.hasTask(task.getType(), task.getObjId()) > 0) {
            return true;
        }
        task.setNextTime(new Date());
        task.setObjId(dr.getId() + "");
        log.info("insert Task:{}", JsonHelper.toJson(task));
        return taskMapper.addTask(task);

    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> query(TakeOutOrder order, AuserShop shop) throws Exception {
        String uri = host + QUERY;
        String body = buildQueryBody(order, shop);
        String req = buildRequest(body, order, shop);
        String resp = HttpClientHelper.doPost(uri, req);
        log.info("request:{},response:{}", req, resp);
        if (StringUtils.isNotBlank(resp)) {
            Map<String, Object> result = JsonHelper.fromJson(resp, Map.class);
            return result;
        } else {
            Map<String, Object> resultMap = new HashMap<String, Object>();
            resultMap.put("status", "error");
            resultMap.put("code", -1);
            resultMap.put("msg", "查询运费服务异常");
            return resultMap;
        }
    }

    private String buildRequest(String body, TakeOutOrder order, AuserShop shop) {
        Map<String, Object> param = new HashMap<>();
        param.put("app_key", appKey);
        param.put("timestamp", (System.currentTimeMillis() / 1000) + "");
        param.put("format", "json");
        param.put("v", "1.0");
        param.put("source_id", shop.getDeliverUid());// order.getShopId());
        param.put("body", body);
        param.put("signature", getSign(param));
        return JsonHelper.toJson(param);
    }

    private String buildQueryBody(TakeOutOrder order, AuserShop shop) {
        Map<String, Object> param = new HashMap<>();
        param.put("origin_id", order.getId());
        param.put("shop_no", shop.getDeliverShopNo());
        param.put("city_code", "020");
        param.put("cargo_price", order.getTotalPrice());
        param.put("is_prepay", 1);
        param.put("expected_fetch_time", String.valueOf(new Date().getTime() / 1000 + 1800));
        param.put("receiver_name", order.getConsigness());
        param.put("receiver_address", order.getDeliverPoi());
        param.put("receiver_phone", order.getPhone());
        param.put("receiver_lat", order.getDeliverLat());
        param.put("receiver_lng", order.getDeliverLon());
        param.put("tips", 0d);
        param.put("cargo_type", 1);
        param.put("callback", callback);
        return JsonHelper.toJson(param);
    }

    private String buildAddTipBody(String order_id, double tips) {
        Map<String, Object> param = new HashMap<>();
        param.put("order_id", order_id);
        param.put("tips", tips);
        param.put("city_code", "020");
        return JsonHelper.toJson(param);
    }

    private String getSign(Map<String, Object> requestMap) {
        // Key值排序
        Collection<String> keySet = requestMap.keySet();
        List<String> list = new ArrayList<String>(keySet);
        Collections.sort(list);

        // 拼凑签名字符串
        StringBuffer signStr = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            String key = list.get(i);
            signStr.append(key + requestMap.get(key));
        }
        // MD5签名
        String mySign = DigestUtils
                .md5DigestAsHex((appSecret + signStr.toString() + appSecret).getBytes(Consts.UTF8_CHARSET));
        String sign = mySign.toUpperCase();
        return sign;
    }

    public static void main(String[] args) throws Exception {
        String str = "appSecretapp_keyapp_keybody{\"order_id\":\"20170301000001\"}formatjsonsource_id73753timestamp1488363493v1.0appSecret";
        System.out.println(new String(DigestUtils.md5DigestAsHex(str.getBytes("utf-8"))));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean cancel(Long id, Integer reason_id) throws Exception {
        // TODO Auto-generated method stub

        try {
            DeliverRecord dr = deliverRecordMapper.getById(id);
            TakeOutOrder entity = orderMapper.getById(dr.getOrderId());
            AuserShop shop = orderMapper.getShop(entity.getShopId(), entity.getType());
            if (dr != null) {

                String uri = host + CANCEL;
                Map<String, Object> param = new HashMap<>();
                param.put("order_id", dr.getId());
                param.put("cancel_reason_id", reason_id);
                if (reason_id == 10000) {
                    param.put("cancel_reason", "其他原因");
                }
                String body = JsonHelper.toJson(param);
                String req = buildRequest(body, entity, shop);
                String resp = HttpClientHelper.doPost(uri, req);
                log.info("request:{},response:{}", req, resp);
                if (StringUtils.isNotBlank(resp)) {
                    Map<String, Object> result = JsonHelper.fromJson(resp, Map.class);
                    if (0 == (Integer) result.get("code") || 2076 == (Integer) result.get("code")
                            || 2005 == (Integer) result.get("code")) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error("", e);
            if (e instanceof ServiceException) {
                throw e;
            }
        }
        return false;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<DadaReasons> getReasonsList(Long id) {
        // TODO Auto-generated method stub
        try {
            DeliverRecord dr = deliverRecordMapper.getById(id);
            TakeOutOrder entity = orderMapper.getById(dr.getOrderId());
            AuserShop shop = orderMapper.getShop(entity.getShopId(), entity.getType());
            String uric = host + CANCEL_REASONS;
            String reqc = buildRequest("", null, shop);
            String respc = HttpClientHelper.doPost(uric, reqc);
            if (StringUtils.isNotBlank(respc)) {
                Map<String, Object> result = JsonHelper.fromJson(respc, Map.class);
                if (0 == (Integer) result.get("code")) {
                    List str = (List) result.get("result");
                    List<DadaReasons> data = JsonHelper.fromJson(JsonHelper.toJson(str),
                            new TypeReference<List<DadaReasons>>() {
                            });
                    return data;
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error("", e);
        }

        return Collections.emptyList();

    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean testOrder(Long orderId, Integer type) {
        // TODO Auto-generated method stub
        try {
            String url = host;
            if (type == 1) {
                url = host + "/api/order/accept";
            } else if (type == 2) {
                url = host + "/api/order/fetch";
            } else if (type == 3) {
                url = host + "/api/order/finish";
            } else if (type == 4) {
                url = host + "/api/order/cancel";
            } else if (type == 5) {
                url = host + "/api/order/expire";
            }

            Map<String, Object> param = new HashMap<>();
            param.put("order_id", orderId);
            AuserShop shop = new AuserShop();
            shop.setDeliverUid("73753");
            String reqc = buildRequest(JsonHelper.toJson(param), null, shop);
            String respc = HttpClientHelper.doPost(url, reqc);
            if (StringUtils.isNotBlank(respc)) {
                Map<String, Object> result = JsonHelper.fromJson(respc, Map.class);
                if (0 == (Integer) result.get("code")) {
                    return true;
                } else {
                    throw new ServiceException(-1, result.get("msg") + "");
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error("", e);

        }
        return false;
    }
}
